package translator.provider;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import translator.Util;

public class SeznamTranslator extends ATranslator<SeznamTranslator.ELang> {

    private static final Logger log = Logger.getLogger(SeznamTranslator.class);

    private static final String URL = "http://slovnik.seznam.cz/?q=";
    private static final String UNDERLINE = "_";
    private static final String LANG_PARAM = "&lang=";
    private static final String METHOD = "GET";

    //parse specific
    private static final String BEGINNING = "\">";
    private static final String ENDING = "</a>";
    private static final String END_OF_TRANS = "</td>";
    private static final String WORDS_BREAK = "id=\"words\"";
    private String word_store;
    private String trans_store;

    public enum ELang implements ATranslator.IELang {
        ENGLISH("en"),
        CZECH("cz");

        private String descriptor;

        private ELang(String desc) {
            descriptor = desc;
        }
        @Override
        public String getDesc() {
            return descriptor;
        }
    }

    @Override
    public void langChanged() {
        word_store = actualFromLang.getDesc() + UNDERLINE + actualToLang.getDesc() + BEGINNING;
        trans_store = actualToLang.getDesc() + UNDERLINE + actualFromLang.getDesc() + BEGINNING;
    }

    @Override
    public ELang[] getSupportedLanguages() {
        return ELang.values();
    }

    public SeznamTranslator() {
        this(ELang.ENGLISH, ELang.CZECH);
    }

    public SeznamTranslator(ELang fromLang, ELang toLang) {
        actualFromLang = fromLang;
        setToLang(toLang);
    }

    @Override
    public LinkedHashSet<String> translate(String wordToTranslate) {

        LinkedHashSet<String> result = new LinkedHashSet<String>();

        StringBuilder url = new StringBuilder(URL + wordToTranslate);
        if(actualFromLang == actualToLang) {
            return result;
        } else {
            url.append(LANG_PARAM);
            url.append(actualFromLang.getDesc());
            url.append(UNDERLINE);
            url.append(actualToLang.getDesc());
        }

        InputStream in = null;
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url.toString()).openConnection();
            conn.setRequestMethod(METHOD);
            in = conn.getInputStream();

            result = parse(in, wordToTranslate);

        } catch (IOException ex) {
            log.error("couldn't get answer from server", ex);
            return result;
        } finally {
            Util.closeStream(in);
        }

        return result;

    }

    private LinkedHashSet<String> parse(InputStream in, String searchWord) throws IOException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        LinkedHashSet<String> result = new LinkedHashSet<String>();

        boolean storeWords = false;
        String word = "";
        Set<String> translations = new LinkedHashSet<String>();

        char[] buff = new char[128];
        StringBuilder buffer = new StringBuilder();
        while(reader.read(buff) != -1) {
            buffer.append(buff);
        }

        while(buffer.indexOf(trans_store) != -1) {

            if(!storeWords) {
                if(buffer.indexOf(WORDS_BREAK) == -1) {
                    break;
                }
                buffer.delete(0, buffer.indexOf(WORDS_BREAK) + WORDS_BREAK.length());

                if(buffer.indexOf(word_store) == -1 || buffer.indexOf(trans_store) == -1) {
                    break;
                }

                storeWords = true;
            } else {
                if(word.isEmpty()) { //load word
                    if(buffer.indexOf(word_store) == -1) {
                        break;
                    }
                    buffer.delete(0, buffer.indexOf(word_store));
                    word = buffer.substring(word_store.length(), buffer.indexOf(ENDING));
                    if(!word.endsWith(searchWord)) {
                        word = "";
                    }
                    buffer.delete(0, buffer.indexOf(word_store) + word.length() + ENDING.length());
                } else { //load translations
                    int transIndex = buffer.indexOf(trans_store);
                    if(transIndex == -1
                            || (transIndex > buffer.indexOf(END_OF_TRANS) && !translations.isEmpty())) {
                        break;
                    }
                    buffer.delete(0, transIndex);
                    String trans = buffer.substring(trans_store.length(), buffer.indexOf(ENDING));
                    translations.add(trans);
                    buffer.delete(0, buffer.indexOf(trans_store) + trans.length() + ENDING.length());
                }
            }
        }

        if(!word.isEmpty()) {
            result.addAll(translations);
        }

        return result;

    }

}
